﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

using log4net;
using ConfigUtilLib;
using QueueMgrUtil;
using CommonLib;


namespace DataProcessorLib
{
    public class DataProcessManager
    {
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        private static DataProcessManager _dataprocessingMgr = null;
        private AppConfig _appConfig { get; set; }
        public BlockReadQueue<QueueWorkItem> WorkItemsQueue;
        private static  CountdownEvent _countdown = null; // Static due to Thread Use in the same class.

        /// <summary>
        /// 
        /// </summary>
        public DataProcessManager()
        {
            WorkItemsQueue = QueueManager.WorkItemsQueue;
        }


        public static DataProcessManager  getDatafetcherSingletonObject()
        {
            if (_dataprocessingMgr == null)
            {
                _dataprocessingMgr = new DataProcessManager();
            }
            return _dataprocessingMgr;
        }
        

        #region PUBLIC_METHODS

        public void  kickOffProcessingData(AppConfig appCfg)
        {
            _appConfig = appCfg;
            ProcessQueuedRequests();
        }
        #endregion

        #region Private Method 

        private  void ProcessQueuedRequests( )
        {
            log.DebugFormat("Starting Processing Thread");
            
            while (true)
            {

                QueueWorkItem workItem = WorkItemsQueue.Dequeue();

                if (workItem != null)
                {
                    if (workItem.cmdType == QUEUE_WORK_ITEM_TYPE.PROCESS_END)
                    {
                        log.DebugFormat(" Completed  Processing All Work Items .. ");
                        if( _countdown != null )
                            _countdown.Wait();
                        return;
                    }

                    if (_countdown == null)
                    {
                        _countdown = new CountdownEvent(1);
                    }
                    else
                    {
                        if (_countdown.CurrentCount == 0)
                        {
                            _countdown = new CountdownEvent(1);
                        }
                        else
                        {
                            _countdown.AddCount();
                        }
                    }
                    //  Let Us spin off a thread to execute this. 
                    ThreadPool.QueueUserWorkItem(ProcessQueuedWorkItemThreadFunction, workItem);

                }
            }

        }

        // Thread
        private static  void ProcessQueuedWorkItemThreadFunction( Object args)
        {
            QueueWorkItem workItem = args as QueueWorkItem;
            workItem.ProcessRawData();
            _countdown.Signal();
        }
        #endregion

    }
}
